﻿///////////////////////////////////////////////////////////////////////////////////////////////
//作者    ：陈国成
//创建时间：2009-10-16
//版本    ：1.0
//描述    ：电子试卷生成策略
//最后修改者：陈国成
//////////////////////////////////////////////////////////////////////////////////////////////
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Entity;
using System.Linq.Expressions;
using Common;
using DAL;
using System.Data.Linq;
namespace BAL
{
    #region


    /// <summary>
    /// //新旧题所点比重对象
    /// </summary>
    public class XmlLatestQuestionRepeat
    {

        /// <summary>
        /// 乘以百分比后的值
        /// </summary>
        public int LatestQuestionValue
        {
            get;
            set;
        }
        /// <summary>
        /// 百分比
        /// </summary>
        public double LatestQuestionPercent
        {
            get;
            set;
        }
        /// <summary>
        /// 操作符
        /// </summary>
        public string OptionType
        {
            get;
            set;
        }
        /// <summary>
        /// 时间
        /// </summary>
        public DateTime OptionTypeValue
        {
            get;
            set;
        }

        /// <summary>
        /// 出现次数
        /// </summary>
        public int AppearanceNum
        {
            get;
            set;
        }
    }

    /// <summary>
    /// 难度系数对象
    /// </summary>
    public class XmlDiff
    {
        /// <summary>
        /// 难度系数Id
        /// </summary>
        public string DiffId
        {
            get;
            set;
        }



        /// <summary>
        /// 难度系数级别
        /// </summary>
        public decimal Coneffic
        {
            get;
            set;
        }

        /// <summary>
        /// 乘以百分比后的值
        /// </summary>
        public int DiffTypeValue
        {
            get;
            set;
        }
        /// <summary>
        /// 百分比
        /// </summary>
        public double DiffTypePercent
        {
            get;
            set;
        }

        /// <summary>
        /// 操作符如 > ,>=
        /// </summary>
        public string DiffOptionType
        {
            get;
            set;
        }

        /// <summary>
        /// 出现次数
        /// </summary>
        public int AppearanceNum
        {
            get;
            set;
        }

        /// <summary>
        /// 这种类型的题保存的个数,和AppearanceNum的值要相等
        /// </summary>
        public List<string> ResourceElectronIds
        {
            get;
            set;
        }
    }

    /// <summary>
    /// 知识点对象
    /// </summary>
    public class XmlKnowPoint
    {
        /// <summary>
        /// 知识点Id
        /// </summary>
        public string KnowPointId
        {
            get;
            set;
        }

        /// <summary>
        /// 乘以百分比后的值
        /// </summary>
        public int KnowPointTypeValue
        {
            get;
            set;
        }

        /// <summary>
        /// 百分比
        /// </summary>
        public double KnowPointTypePercent
        {
            get;
            set;
        }

        /// <summary>
        /// 出现次数
        /// </summary>
        public int AppearanceNum
        {
            get;
            set;
        }
    }

    public class XmlQuestion
    {
        //public string DiffCondtion
        //{
        //    get;
        //    set;
        //}

        //public string KnowPointCondition
        //{
        //    get;
        //    set;
        //}
        //public string LatestQuestionRepeatCondtion
        //{
        //    get;
        //    set;
        //}

        public string SingleCondtion
        {
            get;
            set;
        }

        /// <summary>
        /// 题类型Id
        /// </summary>
        public string Type
        {
            get;
            set;
        }
        /// <summary>
        /// 总分
        /// </summary>
        public decimal AllScore
        {
            get;
            set;
        }
        /// <summary>
        /// 总个数
        /// </summary>
        public int AllCount
        {
            get;
            set;
        }

        /// <summary>
        /// 单题分值
        /// </summary>
        public List<decimal> SingleScore
        {
            get;
            set;
        }

        /// <summary>
        /// 新旧题比例
        /// </summary>
        public List<XmlLatestQuestionRepeat> LatestQuestionRepeats
        {
            get;
            set;
        }

        /// <summary>
        /// 难度
        /// </summary>
        public List<XmlDiff> Diffs
        {
            get;
            set;
        }

        /// <summary>
        /// 知识点
        /// </summary>
        public List<XmlKnowPoint> KnowPoints
        {
            get;
            set;
        }

        /// <summary>
        /// 开始时间
        /// </summary>
        public DateTime? StartDate
        {
            get;
            set;
        }
        /// <summary>
        /// 结束时间
        /// </summary>
        public DateTime? EndDate
        {
            get;
            set;
        }
        /// <summary>
        /// 重复次数
        /// </summary>
        public string AppearNum
        {
            get;
            set;
        }

        public string SubjectId
        {
            get;
            set;
        }
        public List<string> BookIds
        {
            get;
            set;
        }
    }

    #endregion

    public class ElectronTestPagerStratory : BaseElectronTestPagerStratory
    {
        public ElectronTestPagerStratory():base()
        { 
        
        }

        public override IList<QuestionInfo> GenerateElectronTestPager(string content, IList<QuestionInfo> selectedQuestionInfos)
        {
            IList<QuestionInfo> resouce = new List<QuestionInfo>();
            List<Models.Question> list = PreGenerateElectronTestPager(content,selectedQuestionInfos);
            if (list == null) return null;
            if (list.Count() == 0) return null;
            if (QuestionInfo.AllCount <= 0) return null;
            if (QuestionInfo.AllScore <= 0) return null;
            if (list.Count() < QuestionInfo.AllCount) return null;

            if (list.Sum(p => p.Score) < QuestionInfo.AllScore) return null;

            List<Models.Question> tempList = new List<Models.Question>();
            bool isFindSuccess = false;

           
            isFindSuccess = GetResouce(list,ref tempList);

            if (isFindSuccess) //成功
            {
                for (int i = 0; i < tempList.Count(); i++)
                {
                    resouce.Add(BAL.Question.TransQuestion2QuestionInfo(tempList[i]));
                }
            }

            return resouce;
        }

        private bool GetResouce(List<Models.Question> list, ref List<Models.Question> tempList)
        {
  
            int rdValue = 0;
            int allCountTemp = 0; //临时变量，用于存总个数 
            decimal  allScoreTemp = 0; //临时变量，用于存总分数


            Models.Question minScoreItem = new Models.Question(); //分数最大项
            Models.Question maxScoreItem = new Models.Question(); //分数最小项
            Models.Question item; //题临时变量


            Models.Question itemTemp = null;
            bool isFindSuccess = false;   //出题是否成功，成功为true
            XmlKnowPoint xmlKnowPointItem = null;  //知识点Xml对象
            XmlDiff  xmlDiffItem = null;            //难度系数Xml对象 
            DifficInfo  percentElectronDiff = null; //每个题的难度信息

            //XmlLatestQuestionRepeat reaptItem = null; //新旧题对象
            //bool reaptItemTag = false;

            int   hasConditionNum = 0;
            decimal diffrentValue = 0;
            DateTime currentDateTime = new DateTime(DateTime.Now.Ticks);
            int kCount = 0;
            try
            {
                while (true)
                {
                    Random rd = new Random(System.DateTime.Now.Millisecond);
                    rdValue = rd.Next(0, list.Count());
                    hasConditionNum = 0;   //条件数目
                    item = list[rdValue]; //随机取一个题
                    xmlKnowPointItem = null; //知识点类型对象

                    xmlDiffItem = null;      //难度系数对象 

                    percentElectronDiff = null; //每个题的难度信息

                    if (!tempList.Contains(item))
                    {

                        kCount++;
                        #region  取得各种条件

                        //知识点条件

                        if (QuestionInfo.KnowPoints != null && QuestionInfo.Diffs != null && QuestionInfo.Diffs.Count() > 0 && QuestionInfo.KnowPoints.Count() > 0)
                        {
                            hasConditionNum = 2;
                        }
                        else if ((QuestionInfo.Diffs != null && QuestionInfo.Diffs.Count() > 0) || (QuestionInfo.KnowPoints != null && QuestionInfo.KnowPoints.Count() > 0))
                        {
                            hasConditionNum = 1;
                        }
                        else
                        {
                            hasConditionNum = 0;
                        }
                        if (QuestionInfo.KnowPoints != null && QuestionInfo.KnowPoints.Count() > 0)
                        {
                            var query = from qItem in QuestionInfo.KnowPoints
                                        where qItem.KnowPointId == item.KnowId.ToString()
                                        select qItem;
                            foreach (var qXmlItem in query)
                            {
                                xmlKnowPointItem = qXmlItem;
                                break;
                            }
                        }

                        //难度系数条件
                        if (QuestionInfo.Diffs != null && QuestionInfo.Diffs.Count() > 0)
                        {
                            percentElectronDiff = Diffic.GetDifficInfoById(item.DifficId);//当前这个题的难度系数
                            string optype = ""; //操作符如>,>=,=,<,<=
                            decimal level = 0;      //难度级别
                            bool isFind = false;

                            if (percentElectronDiff != null && percentElectronDiff.Id != 0)//这个题的难度系数存在
                            {
                                for (int n = 0; n < QuestionInfo.Diffs.Count(); n++)
                                {
                                    isFind = false;
                                    optype = QuestionInfo.Diffs[n].DiffOptionType; //条件中操作符
                                    level = QuestionInfo.Diffs[n].Coneffic;        //条件中的级别
                                    if (QuestionInfo.Diffs[n].AppearanceNum + 1 <= QuestionInfo.Diffs[n].DiffTypeValue)
                                    {
                                        #region 比较级别
                                        switch (optype)
                                        {
                                            case "=":
                                                if (level == int.Parse( percentElectronDiff.Keyword))
                                                {
                                                    isFind = true;
                                                }
                                                break;
                                            case "<=":
                                                if (level >= int.Parse(percentElectronDiff.Keyword))
                                                {
                                                    isFind = true;
                                                }
                                                break;
                                            case "<":
                                                if (level > int.Parse(percentElectronDiff.Keyword))
                                                {
                                                    isFind = true;
                                                }
                                                break;
                                            case ">":
                                                if (level < int.Parse(percentElectronDiff.Keyword))
                                                {
                                                    isFind = true;
                                                }
                                                break;
                                            case ">=":
                                                if (level <= int.Parse(percentElectronDiff.Keyword))
                                                {
                                                    isFind = true;
                                                }
                                                break;
                                        }

                                        #endregion
                                    }
                                    if (isFind)
                                    {
                                        xmlDiffItem = QuestionInfo.Diffs[n];
                                        break;
                                    }
                                }
                            }

                        }

                      

                        #endregion

                        #region  是否满足其它条件，满足则新增加到tempList列表中


                        if (xmlKnowPointItem != null && xmlDiffItem != null && hasConditionNum==2)
                        {
                            #region  two
                            if (xmlKnowPointItem.AppearanceNum + 1 <= xmlKnowPointItem.KnowPointTypeValue
                                 && xmlDiffItem.AppearanceNum + 1 <= xmlDiffItem.DiffTypeValue)
                            {

                                if (ModifyTempList(list, ref tempList, ref allCountTemp, ref allScoreTemp,item.Score))
                                {

                                    xmlKnowPointItem.AppearanceNum = xmlKnowPointItem.AppearanceNum + 1;
                                    xmlDiffItem.AppearanceNum = xmlDiffItem.AppearanceNum + 1;
                                    if (xmlDiffItem.ResourceElectronIds == null)
                                    {
                                        xmlDiffItem.ResourceElectronIds = new List<string>();
                                    }
                                    xmlDiffItem.ResourceElectronIds.Add(item.Id.ToString());

                                    tempList.Add(item); //取得题放到tempList列表中


                                    list.Remove(item);  //不在list选择这个记录了,这样做的目的使用list + tempList的记录为原来的list的记录总数
                                    allCountTemp++;
                                    allScoreTemp = allScoreTemp + item.Score;
                                }
                            }

                            #endregion
                        }
                        else if (xmlDiffItem != null && hasConditionNum==1)
                        {
                            #region one
                            if (xmlDiffItem.AppearanceNum + 1 <= xmlDiffItem.DiffTypeValue)
                            {
                                if (ModifyTempList(list, ref tempList, ref allCountTemp, ref allScoreTemp, item.Score))
                                {
                                    xmlDiffItem.AppearanceNum = xmlDiffItem.AppearanceNum + 1;
                                    tempList.Add(item); //取得题放到tempList列表中
                                    if (xmlDiffItem.ResourceElectronIds == null)
                                    {
                                        xmlDiffItem.ResourceElectronIds = new List<string>();
                                    }
                                    xmlDiffItem.ResourceElectronIds.Add(item.Id.ToString());

                                    list.Remove(item);  //不在list选择这个记录了,这样做的目的使用list + tempList的记录为原来的list的记录总数

                                    allCountTemp++;
                                    allScoreTemp = allScoreTemp + item.Score;
                                }
                            }
                            #endregion
                        }
                        else if (xmlKnowPointItem != null && hasConditionNum==1)
                        {
                            #region one
                            if (xmlKnowPointItem.AppearanceNum + 1 <= xmlKnowPointItem.KnowPointTypeValue)
                            {
                                if (ModifyTempList(list, ref tempList, ref allCountTemp, ref allScoreTemp, item.Score))
                                {
                                    xmlKnowPointItem.AppearanceNum = xmlKnowPointItem.AppearanceNum + 1;
                                    tempList.Add(item); //取得题放到tempList列表中


                                    //if (xmlDiffItem !=null && xmlDiffItem.ResourceElectronIds == null)
                                    //{
                                    //    xmlDiffItem.ResourceElectronIds = new List<string>();
                                    //}
                                    //if (xmlDiffItem != null)
                                    //{
                                    //    xmlDiffItem.ResourceElectronIds.Add(item.Id.ToString());
                                    //}

                                    list.Remove(item);  //不在list选择这个记录了,这样做的目的使用list + tempList的记录为原来的list的记录总数

                                    allCountTemp++;
                                    allScoreTemp = allScoreTemp + item.Score;
                                }
                            }
                            #endregion
                        }
                        else if(hasConditionNum==0)
                        {
                            if (ModifyTempList(list, ref tempList, ref allCountTemp, ref allScoreTemp, item.Score))
                            {
                                tempList.Add(item); //取得题放到tempList列表中
                                list.Remove(item);  //不在list选择这个记录了,这样做的目的使用list + tempList的记录为原来的list的记录总数
                                allCountTemp++;
                                allScoreTemp = allScoreTemp + item.Score;
                            }
                        }

                      
                        #endregion
                    }

                    #region
                    if (allCountTemp == QuestionInfo.AllCount) //总个数相等了
                    {
                        var queryOrder = from tempListItem in tempList orderby tempListItem.Score ascending select tempListItem;
                        tempList = queryOrder.ToList<Models.Question>();
                        minScoreItem = tempList[0];
                        maxScoreItem = tempList[tempList.Count() - 1];

                        if (allScoreTemp > QuestionInfo.AllScore)  //总个数相等 总分超过了，去掉单题分值最大项
                        {
                            #region
                            tempList.Remove(item); //去掉刚才新增加的那个项，现在的数目是比总数目少一个


                            if (xmlDiffItem != null)
                            {
                                xmlDiffItem.AppearanceNum = xmlDiffItem.AppearanceNum - 1;
                                if (xmlDiffItem.ResourceElectronIds != null)
                                {

                                    xmlDiffItem.ResourceElectronIds.Remove(item.Id.ToString());
                                }
                            }
                            if (xmlKnowPointItem != null)
                            {
                                xmlKnowPointItem.AppearanceNum = xmlKnowPointItem.AppearanceNum - 1;
                            }

                            allScoreTemp = allScoreTemp - item.Score; //总分减少
                            allCountTemp--;                                 //总个数减少



                            diffrentValue = QuestionInfo.AllScore - allScoreTemp; //取两都之差，下面的语句查看有没有单条记录的值为diffrentValue

                            itemTemp = null;
                            if (list.Exists(p => p.Score == diffrentValue))
                            {
                                var singeRecord = list.First(p => p.Score == diffrentValue);
                                if (singeRecord != null)
                                {
                                    itemTemp = singeRecord;
                                }
                            }
                            //不存在这样的记录
                            if (itemTemp == null)
                            {
                                tempList.Remove(maxScoreItem); //去掉分值最大项和原来增加的item项，现在比题总个数少两个了

                                if (QuestionInfo.KnowPoints != null && QuestionInfo.KnowPoints.Count() > 0)
                                {
                                    for (int k = 0; k < QuestionInfo.KnowPoints.Count(); k++)
                                    {
                                        if (QuestionInfo.KnowPoints[k].KnowPointId == maxScoreItem.KnowId.ToString())
                                        {
                                            QuestionInfo.KnowPoints[k].AppearanceNum = QuestionInfo.KnowPoints[k].AppearanceNum - 1;
                                            break;
                                        }
                                    }
                                }
                                if (QuestionInfo.Diffs != null && QuestionInfo.Diffs.Count() > 0)
                                {
                                    for (int k = 0; k < QuestionInfo.Diffs.Count(); k++)
                                    {
                                        if (QuestionInfo.Diffs[k].ResourceElectronIds != null && QuestionInfo.Diffs[k].ResourceElectronIds.Contains(maxScoreItem.Id.ToString()))
                                        {
                                            QuestionInfo.Diffs[k].ResourceElectronIds.Remove(maxScoreItem.Id.ToString());
                                            QuestionInfo.Diffs[k].AppearanceNum = QuestionInfo.Diffs[k].AppearanceNum - 1;
                                            break;
                                        }
                                    }
                                }
                                list.Add(item); //list增加原来的item项 以维护list数据的一致性


                                list.Add(maxScoreItem); //list增加最大项 以维护list数据的一致性


                                allScoreTemp = allScoreTemp - maxScoreItem.Score;
                                allCountTemp--;
                            }
                            else
                            {
                                tempList.Add(itemTemp);
                                allCountTemp++;
                                allScoreTemp = allScoreTemp + itemTemp.Score;
                                isFindSuccess = true; //置成功态


                                break;
                            }

                            #endregion
                        }
                        else if (allScoreTemp < QuestionInfo.AllScore)  //总个数相等 总分没有超过了，去掉单题分值最小项
                        {
                            #region

                            tempList.Remove(item); //去掉刚才新增加的那个项，现在的数目是比总数目少一个

                            if (xmlDiffItem != null)
                            {
                                xmlDiffItem.AppearanceNum = xmlDiffItem.AppearanceNum - 1;
                                if (xmlDiffItem.ResourceElectronIds != null)
                                {
                                    xmlDiffItem.ResourceElectronIds.Remove(item.Id.ToString());
                                }
                            }
                            if (xmlKnowPointItem != null)
                            {
                                xmlKnowPointItem.AppearanceNum = xmlKnowPointItem.AppearanceNum - 1;
                            }
                            allScoreTemp = allScoreTemp - item.Score;  //总分减少
                            allCountTemp--;                 //总个数减少



                            diffrentValue = QuestionInfo.AllScore - allScoreTemp; //取两都之差，下面的语句查看有没有单条记录的值为diffrentValue

                            itemTemp = null;
                            if (list.Exists(p => p.Score == diffrentValue))
                            {
                                var singeRecord = list.First(p => p.Score == diffrentValue);
                                if (singeRecord != null)
                                {
                                    itemTemp = singeRecord;
                                }
                            }

                            //不存在这样的记录
                            if (itemTemp == null)
                            {
                                tempList.Remove(minScoreItem);  //去掉分值最小项和原来增加的item项，现在比题总个数少两个了

                                if (QuestionInfo.KnowPoints != null && QuestionInfo.KnowPoints.Count() > 0)
                                {
                                    for (int k = 0; k < QuestionInfo.KnowPoints.Count(); k++)
                                    {
                                        if (QuestionInfo.KnowPoints[k].KnowPointId == minScoreItem.KnowId.ToString())
                                        {
                                            QuestionInfo.KnowPoints[k].AppearanceNum = QuestionInfo.KnowPoints[k].AppearanceNum - 1;
                                            break;
                                        }
                                    }
                                }
                                if (QuestionInfo.Diffs != null && QuestionInfo.Diffs.Count() > 0)
                                {
                                    for (int k = 0; k < QuestionInfo.Diffs.Count(); k++)
                                    {
                                        if (QuestionInfo.Diffs[k].ResourceElectronIds != null && QuestionInfo.Diffs[k].ResourceElectronIds.Contains(minScoreItem.Id.ToString()))
                                        {
                                            QuestionInfo.Diffs[k].AppearanceNum = QuestionInfo.Diffs[k].AppearanceNum - 1;
                                            QuestionInfo.Diffs[k].ResourceElectronIds.Remove(minScoreItem.Id.ToString());
                                            break;
                                        }
                                    }
                                }
                                list.Add(item); //list增加原来的item项 以维护list数据的一致性


                                list.Add(minScoreItem); //list增加最小项 以维护list数据的一致性


                                allScoreTemp = allScoreTemp - minScoreItem.Score;
                                allCountTemp--;
                            }
                            else
                            {
                                tempList.Add(itemTemp);
                                allCountTemp++;
                                allScoreTemp = allScoreTemp + itemTemp.Score;
                                isFindSuccess = true; //置成功态


                                break;
                            }

                            #endregion
                        }
                        else
                        {
                            isFindSuccess = true; //置成功态


                            break;
                        }
                    }
                    #endregion

                    if (kCount > CircleNumber)
                    {
                        break;
                    }

                    //if (DateTime.Now > currentDateTime.AddHours(CircleNumber))
                    //{
                    //    break;
                    //}
                    

                }
            }
            catch (Exception ex)
            {
                string msg = ex.Message;
               // LogHelper.WriteLog(ex, "GetResouce");
                throw new Exception(ex.Message);
            }
            return isFindSuccess;
        }

        private bool ModifyTempList(List<Models.Question> list, ref List<Models.Question> tempList, ref int allCountTemp, ref decimal allScoreTemp, decimal currentScore)
        {
            bool result = true;
            ///分数大于单值的最大值，则进行调整
            if (allScoreTemp + currentScore > QuestionInfo.AllScore)
            {
                var queryOrder = from tempListItem in tempList orderby tempListItem.Score ascending select tempListItem;
                tempList = queryOrder.ToList<Models.Question>();
                if (tempList.Count() == 0)
                {
                    return false;
                }
                Models.Question maxScoreItem = tempList[tempList.Count() - 1];
                if (currentScore > maxScoreItem.Score)
                {
                    return false;
                }
                #region 
                if (tempList.Remove(maxScoreItem))
                {
                    list.Add(maxScoreItem);

                    allScoreTemp = allScoreTemp - maxScoreItem.Score; //总分减少
                    allCountTemp--;

                    if (QuestionInfo.KnowPoints != null && QuestionInfo.KnowPoints.Count() > 0)
                    {
                        for (int k = 0; k < QuestionInfo.KnowPoints.Count(); k++)
                        {
                            if (QuestionInfo.KnowPoints[k].KnowPointId == maxScoreItem.KnowId.ToString())
                            {
                                QuestionInfo.KnowPoints[k].AppearanceNum = QuestionInfo.KnowPoints[k].AppearanceNum - 1;
                                break;
                            }
                        }
                    }
                    if (QuestionInfo.Diffs != null && QuestionInfo.Diffs.Count() > 0)
                    {
                        for (int k = 0; k < QuestionInfo.Diffs.Count(); k++)
                        {
                            if (QuestionInfo.Diffs[k].ResourceElectronIds != null && QuestionInfo.Diffs[k].ResourceElectronIds.Contains(maxScoreItem.Id.ToString()))
                            {
                                QuestionInfo.Diffs[k].ResourceElectronIds.Remove(maxScoreItem.Id.ToString());
                                QuestionInfo.Diffs[k].AppearanceNum = QuestionInfo.Diffs[k].AppearanceNum - 1;
                                break;
                            }
                        }
                    }
                }

                #endregion
            }
            return result;
        }





    }
}
